<?php
require 'vendor/autoload.php';

use Elasticsearch\ClientBuilder;

class EsScrollExport
{
    /** @var \Elasticsearch\Client */
    private $client;
    /** @var string */
    private $index = 'news_indexbig';
    /** @var int 每批拉取文档数 */
    private $batchSize = 1000;
    /** @var string 滚动保留时间 */
    private $scrollTime = '2m';

    public function __construct(array $config)
    {
        $this->client = ClientBuilder::create()
            ->setHosts([$config['host']])
            ->setBasicAuthentication($config['user'], $config['password'])
            ->build();
    }

    /**
     * 导出所有匹配“成都”的文档
     *
     * @return Generator 每次 yield 一批文档数组
     */
    public function scrollSearch(): \Generator
    {
        // 1. 首次 search 请求，带 scroll 参数
        $params = [
            'index'  => $this->index,
            'scroll' => $this->scrollTime,    // 保留查询上下文 2 分钟 :contentReference[oaicite:0]{index=0}
            'size'   => $this->batchSize,
            'body'   => [
                'query' => [
                    'bool' => [
                        'should' => [
                            [
                                'multi_match' => [
                                    'query'  => '成都',
                                    'type'   => 'phrase_prefix',
                                    'fields' => ['title','daima','faren','province','city','district','address']
                                ]
                            ]
                        ],
                        'minimum_should_match' => 1
                    ]
                ]
            ]
        ];

        $response = $this->client->search($params);
        $scrollId = $response['_scroll_id'];

        // 2. 处理首批结果
        yield $response['hits']['hits'];

        // 3. 循环 scroll 拉取后续批次，直到无数据
        while (true) {
            $response = $this->client->scroll([
                'scroll_id' => $scrollId,
                'scroll'    => $this->scrollTime  // 可在每次调用时延长上下文生命周期 :contentReference[oaicite:1]{index=1}
            ]);

            // 无更多命中，则退出
            if (empty($response['hits']['hits'])) {
                break;
            }

            $scrollId = $response['_scroll_id'];
            yield $response['hits']['hits'];
        }

        // 4. 清理 scroll 上下文，释放资源 
        $this->client->clearScroll([
            'scroll_id' => $scrollId
        ]);
    }
}

// --------- 使用示例 ---------
$config = [
    'host'     => 'https://localhost:9200',
    'user'     => 'elastic',
    'password' => '123456',
];

$exporter = new EsScrollExport($config);

// 将所有批次依次输出或写入文件
foreach ($exporter->scrollSearch() as $batch) {
    foreach ($batch as $doc) {
        // 这里的 $doc['_source'] 即为单个文档内容
        // 例如写入 CSV，或逐条处理
        print_r($doc['_source']);
    }
}
